﻿using Furion.DependencyInjection;
using NewLife.Serialization;
using Newtonsoft.Json;
using Queer.Util;
using Queer.Util.Helper;
using StackExchange.Profiling.Internal;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Queer.Cache.Factory
{
    /// <summary>
    /// redis缓存
    /// </summary>
    public class RedisCache : ISingleton, ICache
    {
        private IDatabase cache;
        private ConnectionMultiplexer connection;

        public RedisCache()
        {
            try
            {
                connection = ConnectionMultiplexer.Connect(GlobalContext.SystemConfig.RedisConnectionString);
                cache = connection.GetDatabase();
            }
            catch (Exception ex)
            {
                LogHelper.Error("redis连接失败：", ex);
                throw new Exception("redis连接失败，请查看日志文件！");
            }
        }

        #region 缓存操作

        /// <summary>
        /// 新增/修改 缓存
        /// </summary>
        public void Set<T>(string key, T value, DateTime? expireTime = null)
        {
            var jsonOption = new JsonSerializerSettings()
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };
            string strValue = JsonConvert.SerializeObject(value, jsonOption);

            if (expireTime == null)
                cache.StringSet(key, strValue);
            else
                cache.StringSet(key, strValue, (expireTime.Value - DateTime.Now));
        }

        /// <summary>
        /// 删除缓存
        /// </summary>
        public void Remove(string key)
        {
            cache.KeyDelete(key);
        }

        /// <summary>
        /// 获取缓存
        /// </summary>
        public T Get<T>(string key)
        {
            var t = default(T);

            var value = cache.StringGet(key);
            if (string.IsNullOrEmpty(value))
            {
                return t;
            }

            if (typeof(T) == typeof(string))
                return (T)(object)value.ToString();

            t = JsonConvert.DeserializeObject<T>(value);

            return t;
        }

        public List<string> GetAllKey()
        {
            var options = ConfigurationOptions.Parse(GlobalContext.SystemConfig.RedisConnectionString);
            var keys = connection.GetServer(options.EndPoints.First()).Keys();
            var list = keys.Select(a => a.ParseToString()).ToList();
            return list;
        }

        #endregion

        #region 队列操作

        /// <summary>
        /// 压栈
        /// </summary>
        public void ListPush(string key, object value)
        {
            // 采用二进制序列化，效率更高
            var data =  Binary.FastWrite(value).ToStr();
            cache.ListLeftPush(key, data);
        }

        /// <summary>
        /// 出栈
        /// </summary>
        public T ListPop<T>(string key)
        {
            var value = cache.ListRightPop(key);

            if (value.HasValue)
            {           
                byte[] array = Encoding.ASCII.GetBytes(value.ToString());
                MemoryStream stream = new MemoryStream(array);
                return Binary.FastRead<T>(stream);
            }
            else
                return default(T);
        }

        #endregion

        public void Dispose()
        {
            if (connection != null)
            {
                connection.Close();
            }
            GC.SuppressFinalize(this);
        }

    }
}